import MapData from "../Map/MapData";
import Constants from "../Constants/Constants";
import G from "./Global";
import Oriented from "../Constants/Oriented";
import C from "../Configs/Config";
import EntityTypes from "../Constants/EntityTypes";

/**
 * 伪寻路辅助类, 存储当前地图所有的可行走区块(数据有冗余)
 * created by Five on 2018-11-29 11:08:42
 */

export default class AStar {
    // 可行走空间
    public _validArea: Map<number, number>;
    private _mapdata: MapData;
    private _xtilecount: number;
    private _deleteh: Array<number>;

    public Init(ms: MapData) {
        this._validArea = new Map<number, number>();
        this._deleteh = new Array<number>();
        this._mapdata = ms;
        this._xtilecount = ms.Size.width / Constants.ENTITY_EDGE;
        for (let i = 0; i < ms.GridCount; i++) {
            if (this.isEmptySpace(G().Calc.LocationToPostion(i)))
                this._validArea.set(i, 0);
        }
        this.calc();
        for (let i = 0; i < this._deleteh.length; i++) {
            this.delete(this._deleteh[i]);
        }
        delete this._deleteh;
        this._deleteh = new Array<number>();
        cc.log(this._validArea);
    }

    calc() {
        this._validArea.forEach((_, k) => {
            this.calcOne(k);
        });
    }

    calcOne(k) {
        let pos = G().Calc.LocationToPostion(k);
        if (!this.isEmptySpace(pos)) {
            return;
        }
        if (!this._validArea.has(k))
            this._validArea.set(k, 0);
        let s = Constants.ENTITY_EDGE;
        let l = cc.v2(-s, 0);
        let d = cc.v2(0, -s);
        let r = cc.v2(s, 0);
        let u = cc.v2(0, s);
        let v = 0;
        if (this.isEmptySpace(pos.add(l)))
            v += Oriented.LEFT;
        if (this.isEmptySpace(pos.add(u)))
            v += Oriented.UP;
        if (this.isEmptySpace(pos.add(r)))
            v += Oriented.RIGHT;
        if (this.isEmptySpace(pos.add(d)))
            v += Oriented.DOWN;
        this._validArea.set(k,v);
        // if (v == Oriented.COUNT) { this._deleteh.push(k) };
    }

    /**
     * 某一格发生了变化
     * @param loc 
     */
    changeOne(loc) {
        this.calcOne(loc);
        this.calcOne(loc + 1);
        this.calcOne(loc - 1);
        this.calcOne(loc + this._xtilecount - 1);
        this.calcOne(loc + this._xtilecount + 1);
        this.calcOne(loc + this._xtilecount);
        this.calcOne(loc - this._xtilecount - 1);
        this.calcOne(loc - this._xtilecount + 1);
        this.calcOne(loc - this._xtilecount);
        // cc.log(this._validArea);
    }

    isEmptySpace(pos: cc.Vec2) {
        let e = this._mapdata.GetWallByPosition(pos);
        if (!e) return true;
        if (e && C().IsTypeOf(e.Asset, EntityTypes.HIDE)) return true;
        return false;
    }

    public add(loc: number) {
        this.calcOne(loc);
        this.changeOne(loc);
    }

    public delete(loc: number) {
        this._validArea.delete(loc);
        this.changeOne(loc);
    }

    public replace(loc: number) {
        this.delete(loc);
        this.add(loc);
    }

    public get(loc: number) {
        return this._validArea.get(loc);
    }

    public getP(pos: cc.Vec2) {
        return this.get(G().Calc.PositionToLocation(pos));
    }

    public has(loc: number): boolean {
        return this._validArea.has(loc);
    }

    public hasP(pos: cc.Vec2): boolean {
        return this.has(G().Calc.PositionToLocation(pos));
    }

    public clear() {
        this._validArea.clear();
    }
}